ホームに戻る
出典 :
関連 :
目次 :
WPFで使用できるファイル選択・保存ダイアログ
Windows Formsでは OpenFileDialog 、SaveFileDialog が標準で使用できたが、
これはWPFと組み合わせて使用されることは想定されておらず、オーナーウィンドウが指定できないなど不便な点が存在する。
Windows API Code Packに含まれる CommonFileDialog は当初から.NETおよびWPFでの使用を前提としているため、WPFとの相性が良い。
(Windows Formsは.NETを謳ってはいるものの、実際はWin32をラッピングしたもので、パフォーマンス等の最適化が十分でない。)
尚、使用できる機能自体はWindows Formsのものと相違は無い。
準備
CommonFileDialog の使用に際しては、Windows API Code Pack を組み込む必要がある。
Windows10以降に適合するのは Microsoft-Windows10-APICodePack-Shell であり、Microsoft-WindowsAPICodePack-Shell とは異なる。
-
Visual Studioの「プロジェクト」>「NuGet パッケージの管理」を選択する。
-
検索欄に "Windows10-APICodePack" と入力し、表示された Microsoft-Windows10-APICodePack-Shell を選択、「インストール」を押下する。
(2022.9.27 時点の最新版は1.1.8。)
-
プロジェクト配下の「パッケージ」に Microsoft-Windows10-APICodePack-Shell 、更にその配下に Microsoft-Windows10-APICodePack-Core が追加されていれば準備完了。
使い方
ファイル選択ダイアログ : CommonOpenFileDialog
// ファイル選択ダイアログを開く
public static string ShowOpenFileDialog( (string[]? extensions, string dispName)[]? filters,
string defaultFileName = "",
string initDir = "",
string title = "ファイルを開く",
Window? owner = null )
{
try
{
// CommonOpenFileDialog の生成
var dialog = new CommonOpenFileDialog(title);
// パラメータの指定
dialog.DefaultFileName = defaultFileName;
dialog.InitialDirectory = initDir;
dialog.EnsureFileExists = true; //< 存在するファイルのみ選択可
dialog.EnsureValidNames = true; //< ファイル名の検証を行う
// フィルタ設定
if( filters is not null )
{
foreach( var f in filters )
{
// 拡張子列が null の場合はスキップ
if( f.extensions is null )
continue;
// フィルタを追加
var st_f = new CommonFileDialogFilter();
st_f.DisplayName = f.dispName;
foreach( var e in f.extensions )
{
st_f.Extensions.Add( e );
}
dialog.Filters.Add( st_f );
}
}
// ダイアログを開く
// オーナーが存在する場合はオーナーを指定
CommonFileDialogResult result = owner is not null ? dialog.ShowDialog(owner) : dialog.ShowDialog();
// 「OK」が押された場合、選択されたファイル名を返す
// それ以外は空文字列を返す
return ( result == CommonFileDialogResult.Ok ) ? dialog.FileName : String.Empty;
}
catch
{
return String.Empty;
}
}
ダイアログを開く際に、選択肢に含めるファイルをフィルタとして指定することができるが、
このフィルタは CommonFileDialogFilterCollection 型で、CommonFileDialogFilter のコレクション(≒List)となっている。即ち、複数のフィルタを設定することができる。
CommonFileDialogFilter は DisplayName (表示名)と Extensions (拡張子の列)で構成されており、ひとつのフィルタに対して複数の拡張子を指定することができる。
尚、拡張子を記述する際には "." (ドット)を含めない。

ここで、EnsureValidNames プロパティを true に指定すると、フィルタのチェックが厳密となり、合致しないファイルを選択肢から除外することができる。
影響を受けるのは ".lnk" (ショートカット)で、リンク先のファイルがフィルタに合致しない場合に選択ができなくなる。
(フォルダリンクはこの限りではない。リンク先のフォルダに遷移し、ダイアログの動作は継続される。)
EnsureValidNames == false だと「リンク先がフィルタに合致しないファイルリンク」を選択できてしまう。
ファイル保存ダイアログ : CommonSaveFileDialog
// ファイル保存ダイアログを開く
public static string ShowSaveFileDialog( (string[]? extensions, string dispName)[]? filters,
string defaultFileName = "",
string initDir = "",
string title = "名前を付けて保存",
Window? owner = null )
{
try
{
// CommonSaveFileDialog の生成
var dialog = new CommonSaveFileDialog(title);
dialog.DefaultFileName = defaultFileName;
dialog.InitialDirectory = initDir;
// フィルタ設定
if( filters is not null )
{
foreach( var f in filters )
{
// 拡張子列が null の場合はスキップ
if( f.extensions is null )
continue;
// フィルタを追加
var st_f = new CommonFileDialogFilter();
st_f.DisplayName = f.dispName;
foreach( var e in f.extensions )
{
st_f.Extensions.Add( e );
}
dialog.Filters.Add( st_f );
}
}
// ダイアログを開く
// オーナーが存在する場合はオーナーを指定
CommonFileDialogResult result = owner is not null ? dialog.ShowDialog(owner) : dialog.ShowDialog();
// 「OK」が押された場合、保存されたファイル名を返す
// それ以外は空文字列を返す
return ( result == CommonFileDialogResult.Ok ) ? dialog.FileName : String.Empty;
}
catch
{
return String.Empty;
}
}
CommonOpenFileDialog が CommonSaveFileDialog となったほかは、前節と同様。
フォルダ選択ダイアログ
public static string ShowFolderBrowserDialog( string initDir = "",
string title = "フォルダを開く",
Window? owner = null )
{
try
{
// CommonOpenFileDialog の生成
var dialog = new CommonOpenFileDialog(title);
dialog.IsFolderPicker = true; //< フォルダ選択オン
dialog.InitialDirectory = initDir;
// ダイアログを開く
// オーナーが存在する場合はオーナーを指定
CommonFileDialogResult result = owner is not null ? dialog.ShowDialog(owner) : dialog.ShowDialog();
// 「OK」が押された場合、選択されたフォルダ名を返す
// それ以外は空文字列を返す
return ( result == CommonFileDialogResult.Ok ) ? dialog.FileName : String.Empty;
}
catch
{
return String.Empty;
}
}
CommonOpenFileDialog を開く際に、IsFolderPicker プロパティを true に指定することでフォルダ選択ダイアログとなる。